import 'package:flutter/gestures.dart';
import 'package:safetymonitor/app/core/core.dart';
import 'package:safetymonitor/app/core/ext/ext.dart';

/// 底部弹框-向下滑动小工具(滑动冲突解决:手势和列表) (Scaffold同级上)
//  @override
//   Widget build(BuildContext context) {
//     return GetBuilder<EnterpriseController>(
//       init: controller,
//       builder: (controller) {
//         return Stack(
//           children: [
//             Scaffold(),
//             NestingBottomCloseOnSwipeDownWidget(
//               scrollController:controller.controller,
//               key: controller.globalKey,
//               backgroundColor: Colors.brown,
//               child: MediaQuery.removePadding(
//                 context: context,
//                 removeTop: true, //去除顶部的空白
//                 child: ListView.builder(
//                   controller: controller.controller,
//                   physics: const ClampingScrollPhysics(),
//                   itemCount: 20,
//                   itemBuilder: (context, index) {
//                     return ListTile(
//                       title: Text('index $index'),
//                     );
//                   },
//                 ),
//               ),
//               voidCallback: () {
//                 AppToast.showSuccess('text');
//               },
//             )
//           ],
//         );
//       },
//     );
//   }
// .clickOnce(() {
//    widget.controller.globalKey.currentState?.startReturnToOriginalPositionAnimation();
//           })
class NestingBottomCloseOnSwipeDownWidget extends StatefulWidget {
  const NestingBottomCloseOnSwipeDownWidget({
    this.scrollController,
    this.voidCallback,
    this.child,
    this.backgroundColor,
    super.key,
    this.borderRadius,
    this.topHeight,
    this.opacity,
  });

  final ScrollController? scrollController;

  ///背景颜色
  final Color? backgroundColor;

  ///距离顶部的高度 =>组件的高度
  final double? topHeight;

  ///圆角
  final BorderRadiusGeometry? borderRadius;

  ///true ? 其他组件 ：列表    其他组件
  final Widget? child;

  ///滑出的回调
  final VoidCallback? voidCallback;
  ///背景透明（0-1之间）
  final double? opacity;

  @override
  NestingBottomCloseOnSwipeDownWidgetState createState() => NestingBottomCloseOnSwipeDownWidgetState();
}

class NestingBottomCloseOnSwipeDownWidgetState extends State<NestingBottomCloseOnSwipeDownWidget> {
  double yOffset = AppDimens.sh;
  double initialPosition = 0.0.w;
  bool isAnimatingOut = false;
  int animTime = 0;
  bool needDrag = true;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Visibility(
          visible: yOffset <= 0 || yOffset <= AppDimens.sh - 100,
          child: Container(
            color: Colors.transparent.withOpacity(widget.opacity ?? 0.5),
          ).clickOnce(startSlideOutAnimation),
        ),
        RawGestureDetector(
          gestures: {
            _MyVerticalDragGestureRecognizer:
                GestureRecognizerFactoryWithHandlers<_MyVerticalDragGestureRecognizer>(_MyVerticalDragGestureRecognizer.new, (_MyVerticalDragGestureRecognizer recognizer) {
              recognizer
                ..onStart = (DragStartDetails details) {
                  initialPosition = details.globalPosition.dy;
                }
                ..onUpdate = (DragUpdateDetails details) {
                  if (yOffset < 0) {
                    //禁止RawGestureDetector往上滑
                    return;
                  }
                  if (!needDrag) {
                    return;
                  }
                  final double updatedPosition = details.globalPosition.dy;

                  final double deltaY = updatedPosition - initialPosition;
                  animTime = 0;
                  setState(() {
                    yOffset = yOffset + deltaY;
                    initialPosition = updatedPosition;
                  });
                }
                ..onEnd = (DragEndDetails details) {
                  animTime = 300;
                  if (yOffset > 200.w) {
                    // 触发滑出动画
                    startSlideOutAnimation();
                  } else {
                    // 触发返回原始位置的动画
                    startReturnToOriginalPositionAnimation();
                  }
                };
            }),
          },
          // behavior: HitTestBehavior.deferToChild,默认
          child: Stack(
            children: [
              AnimatedPositioned(
                duration: Duration(milliseconds: animTime),
                curve: Curves.easeInOut,
                top: yOffset,
                left: 0,
                right: 0,
                child: NotificationListener(
                  //ScrollNotification是一个抽象类，它的子类还有：
                  // ScrollStartNotification：滑动开始通知
                  // ScrollUpdateNotification：滑动中通知，滑动过程中会一直回调
                  // ScrollEndNotification：滑动结束通知
                  // OverscrollNotification：滑动位置未改变通知，这个一般只有在滑动到列表边界才会回调，且需要设置不可越界，即physics为ClampingScrollPhysics，这里要注意安卓默认是这样，但是ios平台默认是弹性边界
                  // UserScrollNotification：用户滑动通知，这个跟ScrollUpdateNotification的区别是他指挥有滑动开始后以及滑动结束后回调
                  onNotification: (ScrollNotification notification) {
                    //滑动位置未改变通知，这个一般只有在滑动到列表边界才会回调，且需要设置不可越界，即physics为ClampingScrollPhysics，这里要注意安卓默认是这样，但是ios平台默认是弹性边界
                    if (notification is OverscrollNotification && notification.overscroll < 0) {
                      // 用户向下滑动，ListView已经滑动到顶部，处理GestureDetector的滑动事件
                      needDrag = true;
                    } else if (notification is ScrollUpdateNotification) {
                      // 用户在ListView中执行滑动动作，关闭外部GestureDetector的滑动处理
                      needDrag = false;
                      // 处理手势向上滑动
                      if (yOffset > 0) {
                        // 当ListView在顶部且手势向上滑动时，允许手势向上滑动
                        needDrag = true;
                        // 禁止列表动
                        widget.scrollController?.animateTo(0, duration: Durations.long4, curve: Curves.ease);
                      }
                    }
                    return false;
                  },
                  child: Column(
                    children: [
                      Container(
                          margin: EdgeInsets.only(top: widget.topHeight?.w != null ? AppDimens.sh - widget.topHeight!.w : AppDimens.sh - 500.w),
                          decoration: BoxDecoration(
                            color: widget.backgroundColor ?? Colors.white,
                            borderRadius: widget.borderRadius ??
                                BorderRadius.only(
                                  topLeft: Radius.circular(10.r),
                                  topRight: Radius.circular(10.r),
                                ),
                          ),
                          height: widget.topHeight?.w != null ? widget.topHeight!.w : AppDimens.sh + 500.w,
                          width: AppDimens.sw,
                          child: widget.child!),
                    ],
                  ),
                ),
                onEnd: () {
                  if (isAnimatingOut) {
                    widget.voidCallback?.call();
                  }
                },
              ),
            ],
          ),
        ),
      ],
    );
  }

  @override
  void dispose() {
    widget.scrollController?.dispose();
    super.dispose();
  }

  ///触发滑出动画
  void startSlideOutAnimation() {
    setState(() {
      isAnimatingOut = true;
      yOffset = AppDimens.sh;
    });
  }

  ///触发滑入动画||触发返回原始位置的动画
  void startReturnToOriginalPositionAnimation() {
    setState(() {
      isAnimatingOut = false;
      yOffset = 0.0;
    });
  }
}

class _MyVerticalDragGestureRecognizer extends VerticalDragGestureRecognizer {
  //而Recognizer在竞技场失败后也可以单方面宣布自己胜出
  //这样即使在竞技场失败了，GestureDetector也能收到后续的手势事件
  //因此我们现定义一个单方面宣布胜出的Recognizer
  @override
  void rejectGesture(int pointer) {
    acceptGesture(pointer);
  }
}
